#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 该文件主要用于配置文件处理的方法
import os
import configparser
from commons.logger import log
from config.path import CONF_DIR

# curDir = os.path.join(os.path.dirname(os.path.dirname(__file__)))  # 当前文件所在目录的上一级目录
# configPath = os.path.join(CONF_DIR, r"config/pytest.ini")  # 拼接要引用的配置文件的完整目录

class Config:

    def __init__(self, config_name):
        """
        初始化方法，接收配置文件名称作为参数，拼接出配置文件的完整路径，并读取配置文件内容
        :param config_name: 配置文件名称，例如 "pytest.ini"
        """
        log.info(f"开始初始化 Config 类，配置文件名称: {config_name}")
        self.config_name = config_name
        self.configpath = os.path.join(CONF_DIR, self.config_name)
        log.info(f"使用的配置文件路径为: {self.configpath}")
        self.config = configparser.ConfigParser(allow_no_value=True)
        self.load_config()
        log.info("Config 类初始化完成")

    def load_config(self):
        """重新加载配置文件"""
        try:
            self.config.read(self.configpath, encoding='utf-8')
            log.info(f"成功重新加载配置文件: {self.configpath}")
        except FileNotFoundError:
            log.error(f"配置文件 {self.configpath} 未找到")
        except Exception as e:
            log.error(f"重新加载配置文件 {self.configpath} 时发生错误: {e}")

    def get_sections(self):
        """
        读取配置文件下所有的分组,以列表形式返回
        """
        log.info("开始获取配置文件的所有分组")
        try:
            sections_list = self.config.sections()
            log.info(f"成功获取配置文件的所有分组: {sections_list}")
            return sections_list
        except Exception as e:
            log.error(f"获取配置文件的所有分组时发生错误: {e}")
            return []

    def get_options(self, section):
        """
        读取配置文件某分组下的所有项,以列表形式返回
        :param section: 分组名
        """
        log.info(f"开始获取配置文件分组 {section} 下的所有项")
        if not isinstance(section, str):
            log.error(f"分组名必须为字符串类型，当前输入: {section}")
            return []
        try:
            option_list = self.config.options(section)
            log.info(f"成功获取配置文件分组 {section} 下的所有项: {option_list}")
            return option_list
        except configparser.NoSectionError:
            log.error(f"配置文件中不存在分组 {section}")
            return []
        except Exception as e:
            log.error(f"获取配置文件分组 {section} 下的所有项时发生错误: {e}")
            return []

    def remove_options(self, section, option):
        """
        功能：删除配置文件分组下的项
        :param section: 分组名
        :param option: 分组下的项名
        :return: 返回删除后的该分组下的项 list
        """
        log.info(f"开始删除配置文件分组 {section} 下的项 {option}")
        if not isinstance(section, str) or not isinstance(option, str):
            log.error(f"分组名和项名必须为字符串类型，当前输入: 分组名 {section}, 项名 {option}")
            return []
        try:
            self.config.remove_option(section, option)  # 删除操作
            with open(self.configpath, 'w+', encoding="utf-8") as f:
                self.config.write(f)
                f.flush()  # 刷新Python文件对象的缓冲区
                os.fsync(f.fileno())  # 确保数据被物理写入磁盘
            option_list = self.get_options(section)
            log.info(f"成功删除配置文件分组 {section} 下的项 {option}，当前分组下的项: {option_list}")
            return option_list
        except configparser.NoSectionError:
            log.error(f"配置文件中不存在分组 {section}")
            return []
        except Exception as e:
            log.error(f"删除配置文件分组 {section} 下的项 {option} 时发生错误: {e}")
            return []

    def read_config_ini(self, section, option):
        """
        读取配置文件某分组下某个项的值
        :param section: 分组名
        :param option: 分组下的项名
        """
        self.load_config()  # 重新加载配置文件
        log.info(f"开始读取配置文件分组 {section} 下项 {option} 的值")
        if not isinstance(section, str) or not isinstance(option, str):
            log.error(f"分组名和项名必须为字符串类型，当前输入: 分组名 {section}, 项名 {option}")
            return None
        section_lst = self.get_sections()  # 获取到配置文件中所有分组名称
        if section not in section_lst:  # 如果分组 type 不存在则报错
            log.error(f"该分组: {section}, 不存在, 请检查配置文件或核对请求参数！")
            return None
        try:
            op_value = self.config.get(section, option)
            log.info(f"成功读取配置文件数据: {section} 分组, {option} 项下的值为 {op_value}")
            return op_value
        except configparser.NoOptionError:
            log.error(f"配置文件分组 {section} 下不存在项 {option}")
            return None
        except Exception as e:
            log.error(f"读取配置文件分组 {section} 下项 {option} 的值时发生错误: {e}")
            return None

    def set_config_ini(self, section, option, op_val):
        """
        写入配置文件,已存在该分组则修改该组下某项的值,不存在该分组则追加该分组并写入对应的项及值
        :param section: 分组名
        :param option: 分组下的项名
        :param op_val: 项对应的值
        """
        log.info(f"开始写入或修改配置文件分组 {section} 下项 {option} 的值为 {op_val}")
        if not isinstance(section, str) or not isinstance(option, str):
            log.error(f"分组名和项名必须为字符串类型，当前输入: 分组名 {section}, 项名 {option}")
            return
        section_lst = self.get_sections()  # 获取到配置文件中所有分组名称
        try:
            if section not in section_lst:  # 如果分组 type 不存在则插入 type 分组
                self.config.add_section(section)
            self.config.set(section, option, str(op_val))  # 给分组设置值
            with open(self.configpath, 'w+', encoding="utf-8") as f:
                self.config.write(f)
                f.flush()  # 刷新Python文件对象的缓冲区
                os.fsync(f.fileno())  # 确保数据被物理写入磁盘
            log.info(f"成功修改或新增配置文件数据: {section} 分组, {option} 项下的值为 {op_val}")
        except Exception as e:
            log.error(f"写入或修改配置文件分组 {section} 下项 {option} 的值时发生错误: {e}")
            raise  # 抛出异常


if __name__ == '__main__':
    a = Config('storage.ini')
    print(a.configpath)
    url = a.read_config_ini("envHost", "hostname")
    print(url)